package com.example.fund.amplitude;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.example.fund.info.FundInfo;
import com.example.fund.util.StringUtil;

public class Amplitude implements IAmplitude {

	@Override
	public List<String> getAmplitudeDateList(FundInfo info,List<String> dateList, double pRate, double nRate)
	{
		return getAmplitudeDateList(info.getActualValues(),dateList,pRate,nRate);
	}
	@Override
	public List<String> getAmplitudeDateList(Map<String, String> actValues,List<String> dateList, double pRate, double nRate)
	{
		List<String> amplitudeDateList = new LinkedList<String>();
		if(actValues.size()==0
				|| dateList==null || dateList.size()==0
				|| pRate<=0 || nRate>=0)
		{
			return amplitudeDateList;
		}
		pRate = pRate/100.00d;
		nRate = nRate/100.00d;

		double max = -1;//记录阶段最大值
		String maxDate = null;
		double min = -1;//记录阶段最大值左侧最小值
		String minDate = null;
		boolean upRise = false;//向上涨幅是否是达成

		//初始化阶段最大值和最小值为第一个值
		int j=dateList.size()-1;
		for(;j>=0;j--) {
			String dateStr = dateList.get(j);
			String vStr = actValues.get(dateStr);
			if (StringUtil.isNullOrEmpty(vStr)) {
				continue;
			}
			double v = Double.valueOf(vStr);//当前值
			//初始化值
			min = v;
			minDate = dateStr;
			max = v;
			maxDate = dateStr;

			break;
		}

		for(int i=j-1;i>=0;i--) {
			String dateStr = dateList.get(i);
			String vStr = actValues.get(dateStr);
			if (StringUtil.isNullOrEmpty(vStr)) {
				continue;
			}
			double v = Double.valueOf(vStr);//当前值
			if (!upRise)//向上涨幅达成前，寻找最低点和最低点右侧的最高点
			{
				if (v < min) {
					min = v;
					minDate = dateStr;
					max = v;
					maxDate = dateStr;
				}
				if (v > max) {
					max = v;
					maxDate = dateStr;

					double pRate1 = (max - min) / min;//每次找到最低点右侧的最高点时，检查向上涨幅是否达成
					upRise = pRate1 >= pRate;//向上涨幅是否是达成
				}
			}
			if (upRise)//向上涨幅达成后，向右寻找向下跌幅达成点
			{
				double nRate1 = (v - max) / max;//向下跌幅
				if (nRate1 < nRate)//向下跌幅达成
				{
					amplitudeDateList.add(minDate);
					amplitudeDateList.add(maxDate);
					//重置
					upRise = false;
					min = v;
					minDate = dateStr;
					max = v;
					maxDate = dateStr;
				}

				if (v > max) {
					max = v;
					maxDate = dateStr;
				}
			}
			if (i==0)
			{
				if (!amplitudeDateList.contains(minDate))
				{
					amplitudeDateList.add(minDate);
				}
				if (!amplitudeDateList.contains(maxDate))
				{
					amplitudeDateList.add(maxDate);
				}
				if (!amplitudeDateList.contains(dateStr))
				{
					amplitudeDateList.add(dateStr);
				}
			}
		}

		return amplitudeDateList;
	}

	public List<String> getAmplitudeDateList1(FundInfo info,
			List<String> dateList, double pRate, double nRate) 
	{
		List<String> amplitudeDateList = new LinkedList<String>();
		if(info==null || info.getActualValues().size()==0 
				|| dateList==null || dateList.size()==0
				|| pRate<=0 || nRate>=0)
		{
			return amplitudeDateList;
		}
		
		boolean flag = (1+pRate/100.00d)*(1+pRate/100.00d)>1;
		List<String> maxDateList = new LinkedList<String>();
		
		double max = -1;
		String maxDate = null;
		double refValue1 = -1;
		String lastSureMaxDate = null;
		
		double min = -1;
		String minDate = null;
		double refValue2 = -1;
		
		Map<String, String> actValues = info.getActualValues();
		boolean shift = true;//true:确认当前min是否为阶段低点;false:确认当前max是否为阶段高点
		for(int j=dateList.size()-1;j>=0;j--)
		{
			String dateStr = dateList.get(j);
			String actValueStr = actValues.get(dateStr);
			if(actValueStr==null)
			{
				continue;
			}
			double actValue = Double.valueOf(actValueStr);//当前值
			//初始化值
			if(min==-1)
			{
				min = actValue;
				minDate = dateStr;
				refValue2 = min*(1+pRate/100.00d);
			}
			if(shift)//确认当前min是否为阶段低点
			{
				if(actValue<min)
				{
					min = actValue;
					minDate = dateStr;
					refValue2 = min*(1+pRate/100.00d);
				}
				
				if(flag && maxDateList.size()>0)
				{
					if(actValue>max)
					{
						max = actValue;
						maxDate = dateStr;
						refValue1 = max*(1+nRate/100.00d);
					}
					if(!maxDateList.contains(maxDate) && actValue<=refValue1)
					{
						maxDateList.add(maxDate);
					}
				}
				
				
				if(actValue>=refValue2)
				{
					if(flag && maxDateList.size()>1)
					{
						double max2 = -1;
						String max2Date = null;
						for(int k=0,s=maxDateList.size();k<s;k++)
						{
							String date = maxDateList.get(k);
							double value = Double.valueOf(actValues.get(date));
							if(value>max2 && date.compareTo(minDate)<0)
							{
								max2 = value;
								max2Date = date;
							}
						}
						if(max2Date!=null && !max2Date.equals(lastSureMaxDate))
						{
							amplitudeDateList.remove(lastSureMaxDate);
							amplitudeDateList.add(max2Date);
						}
					}
					
					amplitudeDateList.add(minDate);
					max = actValue;
					maxDate = dateStr;
					refValue1 = max*(1+nRate/100.00d);
					shift = false;
					
					maxDateList.clear();
				}
				if(j==0 && !amplitudeDateList.contains(minDate))
				{
					if(flag && maxDateList.size()>1)
					{
						double max2 = -1;
						String max2Date = null;
						for(int k=0,s=maxDateList.size();k<s;k++)
						{
							String date = maxDateList.get(k);
							double value = Double.valueOf(actValues.get(date));
							if(value>max2 && date.compareTo(minDate)<0)
							{
								max2 = value;
								max2Date = date;
							}
						}
						if(max2Date!=null && !max2Date.equals(lastSureMaxDate))
						{
							amplitudeDateList.remove(lastSureMaxDate);
							amplitudeDateList.add(max2Date);
						}
					}
					
					amplitudeDateList.add(minDate);
				}
			}else//确认当前max是否为阶段高点
			{
				if(actValue>max)
				{
					max = actValue;
					maxDate = dateStr;
					refValue1 = max*(1+nRate/100.00d);
				}
				if(actValue<=refValue1)
				{
					amplitudeDateList.add(maxDate);
					min = actValue;
					minDate = dateStr;
					refValue2 = min*(1+pRate/100.00d);
					shift = true;
					
					maxDateList.add(maxDate);
					lastSureMaxDate = maxDate;
				}
				if(j==0 && !amplitudeDateList.contains(maxDate))
				{
					amplitudeDateList.add(maxDate);
				}
			}
		}
		String lastDate = dateList.get(0);
		if(!amplitudeDateList.contains(lastDate))
		{
			amplitudeDateList.add(lastDate);
		}
		
		return amplitudeDateList;
	}

	@Override
	public Map<String, String> getAmplitudeDateMap(FundInfo info,List<String> dateList, double pRate, double nRate)
	{
		List<String> amplitudeDateList = getAmplitudeDateList(info,dateList,pRate,nRate);
		Map<String,String> amplitudeDateMap = getAmplitudeDateMap(info,amplitudeDateList);
		
		return amplitudeDateMap;
	}

	@Override
	public Map<String, String> getAmplitudeDateMap(FundInfo info,List<String> amplitudeDateList)
	{
		Map<String,String> amplitudeDateMap = new HashMap<String,String>();

		if(amplitudeDateList==null || amplitudeDateList.size()<2)
		{
			return amplitudeDateMap;
		}

		double lastValue = -1;

		for(int i=0;i<amplitudeDateList.size();i++)
		{
			String dateStr = amplitudeDateList.get(i);
			String actValueStr = info.getActualValues().get(dateStr);
			if(actValueStr==null)
			{
				continue;
			}
			if(lastValue==-1)
			{
				lastValue = Double.valueOf(actValueStr);
			}
			double value = Double.valueOf(actValueStr);
			double rate = 100*(value-lastValue)/lastValue;
			amplitudeDateMap.put(dateStr, new BigDecimal(rate).setScale(0, RoundingMode.HALF_UP).toString());
			lastValue = value;
		}

		return amplitudeDateMap;
	}
	@Override
	public Map<String, String> getAmplitudeDateMap(Map<String, String> values,List<String> amplitudeDateList)
	{
		Map<String,String> amplitudeDateMap = new HashMap<String,String>();

		if(amplitudeDateList==null || amplitudeDateList.size()<2)
		{
			return amplitudeDateMap;
		}

		double lastValue = -1;

		for(int i=0;i<amplitudeDateList.size();i++)
		{
			String dateStr = amplitudeDateList.get(i);
			String actValueStr = values.get(dateStr);
			if(actValueStr==null)
			{
				continue;
			}
			if(lastValue==-1)
			{
				lastValue = Double.valueOf(actValueStr);
			}
			double value = Double.valueOf(actValueStr);
			double rate = 100*(value-lastValue)/lastValue;
			amplitudeDateMap.put(dateStr, new BigDecimal(rate).setScale(0, RoundingMode.HALF_UP).toString());
			lastValue = value;
		}

		return amplitudeDateMap;
	}
}
